#include<iostream>
#include<unistd.h>
#include<cstring>
#include<vector>
#include<string>
#include<stdlib.h>
#include<assert.h>
#include<functional>
#include<sys/types.h>
#include<sys/wait.h>
#include<time.h>

using namespace std;
#define PROCESS_NUM 5
typedef function<void()> func;

class subEp // Endpoint
{
public:
    subEp(pid_t subId, int writeFd)
        : _subId(subId), _writeFd(writeFd)
    {
        char nameBuffer[1024];
        snprintf(nameBuffer, sizeof nameBuffer, "process-%d[pid(%d)-fd(%d)]", _num++, _subId, _writeFd);
        _name = nameBuffer;
    }

public:
    static int _num;
    std::string _name;
    pid_t _subId;
    int _writeFd;
};

int subEp::_num = 0;

int recvTask(int readFd)
{
    int code = 0;
    ssize_t s = read(readFd, &code, sizeof code);
    if(s == 4)
    {
        return code;
    }
    else if(s <= 0)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}

void createProcess(vector<subEp>& subs, vector<func>& funcMap)
{
    for(int i = 0; i <  PROCESS_NUM; i++)
    {
        int fds[2];
        int n = pipe(fds);
        assert(n == 0);
        (void)n;

        pid_t id = fork();
        if(id == 0)
        {
            //子进程，进行任务处理
            close(fds[1]);
            while(true)
            {
                // 1. 获取命令码，如果没有发送，我们子进程应该阻塞
                int commandCode = recvTask(fds[0]);
                // 2. 完成任务
                if (commandCode >= 0 && commandCode < funcMap.size())
                    funcMap[commandCode]();
                else if(commandCode == -1)
                    break;
            }

            close(fds[0]);
            exit(0);
        }
        close(fds[0]);
        subEp sub(id, fds[1]);
        subs.push_back(sub);
    }
}


void sendTask(const subEp& process, int taskNum)
{
    cout << "send task num:" << taskNum << " send to->" << process._name << endl;
    int n = write(process._writeFd, &taskNum, sizeof(taskNum));
    assert(n == sizeof(int));
}

void loadBlanceContrl(vector<subEp>& subs, vector<func>& funcMap)
{
    int processNum = subs.size();
    int taskNum = funcMap.size();
  
    while(true)
    {
        //1.选择一个子进程
        int subIndex = rand() % processNum;
        //2.选择一个任务
        int taskIndex = rand()% taskNum;
        //3.任务发送给选择的进程
        sendTask(subs[subIndex], taskIndex);
        sleep(1);
    }
    

    for(int i = processNum; i >= 0; i--)
    {
        close(subs[i]._writeFd);//waitpid()
    }
}

void waitProcess(vector<subEp> process)
{
    int size = process.size();
    int n = 0;
    for(int i = 0; i < size; i++)
    {
        waitpid(process[i]._subId, nullptr, 0);
        cout << "wait process success ... : " << process[i]._subId << endl;
    }
}

int main()
{
    srand(time(0));
    //1.建立子进程，建立和子进程通信的信道，进行读取
    //1.1 加载方法表
    //[子进程， fds]
    vector<subEp> subs;
    vector<func> funcMap;

    funcMap.push_back([]{cout << "getpid: " << getpid() << " 下载任务" << endl;sleep(1);});
    funcMap.push_back([]{cout << "getpid: " << getpid() << " IO任务" << endl;sleep(1);});
    funcMap.push_back([]{cout << "getpid: " << getpid() << " 刷新任务" << endl;sleep(1);});
    
    createProcess(subs, funcMap);

    //2.父进程控制子进程进行写入
    loadBlanceContrl(subs, funcMap);

    //3.回收子进程信息
    waitProcess(subs);
    return 0;
}
